<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>tetris</title>
  <style type="text/css">
    .activityModel { margin: 1px; width: 19px; height: 19px; background: red; position: absolute; }
    .stationaryModel { margin: 1px; width: 19px; height: 19px; background: gray; position: absolute; }
    .container { top: 0px; left: 0px; width: 200px; height: 360px; background: black; position: absolute; }
  </style>
  <script type="text/javascript">

    var SHAPES = [
      [0, 1, 1, 1, 2, 1, 3, 1],
      [1, 0, 1, 1, 1, 2, 2, 2],
      [2, 0, 2, 1, 2, 2, 1, 2],
      [0, 1, 1, 1, 1, 2, 2, 2],
      [1, 2, 2, 2, 2, 1, 3, 1],
      [1, 1, 2, 1, 1, 2, 2, 2],
      [0, 2, 1, 2, 1, 1, 2, 2]
    ];

    var x = 0;
    var y = 0;
    var shape = [];
    var shapeDiv = [];
    var container = {};

    var intervalId;
    var intervalId2;

    var size = 20;
    var rowCount = 18;
    var colCount = 10;
    var speed = 600;


    function init() {

      create();
      show();

      // 绑定键盘事件
      document.onkeydown = function(e) {
        var e = window.event ? window.event : e;
        switch (e.keyCode) {
          case 32: //quickDown
            quickDown();
            break;
          case 38: //rotate
            rotate(0, -1);
            break;
          case 40: //down
            move(0, 1);
            break;
          case 37: //left
            move(-1, 0);
            break;
          case 39: //right
            move(1, 0);
            break;
        }
      }

      // 方块开始下降
      intervalId = setInterval("move(0, 1)", speed);
    }

    // 随机获取一个方块数组
    var randomShape = function() {
      shape = SHAPES[Math.floor(Math.random() * 7)];
    }

    // 创建方块
    var create = function() {
      x = 3;
      y = 0;
      shapeDiv = [];
      randomShape();
      for (var i = 0; i < 4; i++) {
        var div = document.createElement("div");
        div.className = "activityModel";
        shapeDiv[i] = div;
        document.body.appendChild(div);
      }
    }

    // 显示方块
    var show = function() {
      var divs = document.getElementsByClassName("activityModel");
      for (var j = 0; j < divs.length; j++) {
        divs[j].style.top = (shape[j * 2 + 1] + y) * size + "px";
        divs[j].style.left = (shape[j * 2] + x) * size + "px";
      }
    }

    // 旋转方块
    var rotate = function() {
      var newShape = [shape[1], 3 - shape[0], shape[3], 3 - shape[2], shape[5], 3 - shape[4], shape[7], 3 - shape[6]];
      if (!check(x, y, newShape)) return;
      shape = newShape;
      show();
    }

    // 移动方块
    var move = function(a, b) {
      if (check(x + a, y + b, shape)) {
        x += a;
        y += b
        show();
      } else {
        if (b == 0) return; // 水平移动直接返回
        fix();
        create();
        show();
        clearInterval(intervalId2);
      }
    }

    // 快速下落
    var quickDown = function() {
      intervalId2 = setInterval("move(0, 1)", 0);
    }

    // 固定方块，变成灰色，缓存到容器中
    var fix = function() {
      var divs = document.getElementsByClassName("activityModel");
      for (var i = divs.length - 1; i >= 0; i--) {
        var px = shape[2 * i + 1] + y;
        var py = shape[2 * i] + x;
        container[px + "_" + py] = shapeDiv[i];
        divs[i].className = "stationaryModel";
      }
      findFull();
    }

    // 遍历整个容器，判断是否可以消除
    var findFull = function() {
      var s = 0;
      for (var m = 0; m < rowCount; m++) {
        var count = 0;
        for (var n = 0; n < colCount; n++) {
          if (container[m + "_" + n])
            count++;
        }
        if (count === colCount) {
          s++;
          removeLine(m);
        }
      }
    }

    // 消除指定一行方块
    var removeLine = function(rowCount) {
      // 移除一行方块
      for (var n = 0; n < colCount; n++)
        document.body.removeChild(container[rowCount + "_" + n]);
      // 把所消除行上面所有的方块下移一行
      for (var i = rowCount; i > 0; i--) {
        for (var j = 0; j < colCount; j++) {
          container[i + "_" + j] = container[(i - 1) + "_" + j]
          if (container[i + "_" + j])
            container[i + "_" + j].style.top = i * size + "px";
        }
      }
    }

    // 检查边界越界
    var check = function(x, y, shape) {
      var divs = document.getElementsByClassName("activityModel");

      var most_left = colCount;
      var most_right = 0;
      var most_top = rowCount;
      var most_bottom = 0;
      var overlap = false;

      for (var i = divs.length - 1; i >= 0; i--) {
        // 记录方块最左边坐标
        if (shape[2 * i] < most_left)
          most_left = shape[2 * i];
        // 记录方块最右边坐标
        if (shape[2 * i] > most_right)
          most_right = shape[2 * i];
        // 记录方块最上边坐标
        if (shape[2 * i + 1] < most_top)
          most_top = shape[2 * i + 1];
        // 记录方块最下边坐标
        if (shape[2 * i + 1] > most_bottom)
          most_bottom = shape[2 * i + 1];
        // 判断方块之间是否重叠
        var px = shape[2 * i + 1] + y;
        var py = shape[2 * i] + x;
        if (container[px + "_" + py])
          overlap = true;
      }

      if ((most_right + x + 1) > colCount || (most_left + x) < 0 ||
        (most_bottom + y + 1) > rowCount || (most_top + y) < 0 || overlap)
        return false;

      return true;
    }

  </script>
</head>
<body onload="init()">
    <div class="container"></div>
</body>
</html>